home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / route.arc / PCBPRINT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-24  |  12.4 KB  |  413 lines

  1. /*
  2. ** printed circuit board printer, Copyright (C) Randy Nevin 1989.
  3. **
  4. ** you may give this software to anyone, make as many copies as you like, and
  5. ** post it on public computer bulletin boards and file servers. you may not
  6. ** sell it or charge any fee for distribution (except for media and postage),
  7. ** remove this comment or the copyright notice from the code, or claim that
  8. ** you wrote this code or anything derived from it. you may modify the code as
  9. ** much as you want (please document clearly with comments, and maintain the
  10. ** coding style), but programs which are derived from this one are subject to
  11. ** the conditions stated here. i am providing this code so that people can
  12. ** learn from it, so if you distribute it, please include source code, not
  13. ** just executables. contact me to report bugs or suggest enhancements; i do
  14. ** not guarantee support, but i will make an effort in good faith to help you,
  15. ** and i want to act as a central clearing house for future versions. you
  16. ** should contact me before undertaking a significant development effort, to
  17. ** avoid reinventing the wheel. if you come up with an enhancement you
  18. ** consider particularly useful, i would appreciate being informed so that it
  19. ** can be incorporated in future versions. my address is: Randy Nevin,
  20. ** 1731 211th PL NE, Redmond, WA 98053. this code is available directly from
  21. ** the author; just send a floppy and a self-addressed floppy mailer with
  22. ** sufficient postage.
  23. **
  24. ** HISTORY
  25. ** (name        date        description)
  26. ** ----------------------------------------------------
  27. ** randy nevin        3/4/89        initial version
  28. ** randy nevin        3/4/89        released version 1.00
  29. */
  30.  
  31. #include <stdio.h>
  32.  
  33. #ifndef M_XENIX
  34. #include <stdlib.h>
  35. #endif
  36.  
  37. #include <string.h>
  38. #include "cell.h"
  39.  
  40. /*
  41. ** usage: PCBPRINT [/P] [/L] [/Rn] [/Zm] infile
  42. **
  43. ** /P indicates portrait orientation (paper is longer from top to bottom), and
  44. ** /L indicates landscape orientation (paper is longer side-to-side). only one
  45. ** of /P and /L can be present. n is the laser printer resolution (75, 100,
  46. ** 150, or 300) and m is the zoom factor (0, 1, 2, or 3 ). the defaults are:
  47. ** /P /R150 /Z1. this program creates 6 output files (H, T, B, HT, HB, and
  48. ** HTB). each of these files can be fed to a hewlett-packard laser printer to
  49. ** produce a picture of part or all of the routed printed circuit board. H
  50. ** contains commands to print only the holes and routing holes. T and B
  51. ** contain commands to print only the top-side or bottom-side traces,
  52. ** respectively. HT and HB are the same, but also include the holes, and HTB
  53. ** contains everything (holes, top-side traces, and bottom-side traces).
  54. */
  55.  
  56. #define MAXZOOM    3    /* maximum zoom number; minimum is 0 */
  57.  
  58. #define ZOOM0    3    /* 3x3 dots per cell    */
  59. #define ZOOM1    6    /* 6x6 dots per cell    */
  60. #define ZOOM2    10    /* 10x10 dots per cell    */
  61. #define ZOOM3    18    /* 18x18 dots per cell    */
  62.  
  63. static int size[MAXZOOM+1] = { ZOOM0, ZOOM1, ZOOM2, ZOOM3 };
  64.  
  65. #define H    1    /* holes                */
  66. #define T    2    /* top-side traces            */
  67. #define B    4    /* bottom-side traces            */
  68. #define HT    (H+T)    /* holes and top-side traces        */
  69. #define HB    (H+B)    /* holes and bottom-side traces        */
  70. #define HTB    (H+T+B)    /* holes, top- and bottom-side traces    */
  71.  
  72. static int currnt;    /* current image type (one of the six above)    */
  73. static int orient;    /* 0=portrait, 1=landscape            */
  74. static int resol;    /* resolution (one of 75,100,150,300)        */
  75. static int zoom;    /* 0=3x3, 1=6x6, 2=10x10, 3=18x18        */
  76. static int nbytes;    /* number of bytes per image row        */
  77.  
  78. int justboard = 1; /* only need the board data structure */
  79.  
  80. /* board dimensions */
  81. extern int Nrows;
  82. extern int Ncols;
  83.  
  84. extern void InitBoard( void );
  85. extern long GetCell( int, int, int );
  86. extern void SetCell( int, int, int, long );
  87.  
  88. void main( int, char *[] );
  89. static void dofile( char *, int );
  90. static void prolog( FILE * );
  91. static void epilog( FILE * );
  92. static void doimage( FILE * );
  93. static void map( long, long, int, FILE * );
  94. static void initbit( void );
  95. static void flushbit( FILE * );
  96. static void outbit( int, FILE * );
  97.  
  98. void main ( argc, argv ) /* input routed board, output laser printer files */
  99.     int argc;
  100.     char *argv[];
  101.     {
  102.     char *self, *p;
  103.     register int r, c;
  104.     int i1, i2, i3, i4, i, j;
  105.     FILE *fp;
  106.     long x;
  107.     char oset, rset, zset;
  108.  
  109.     printf( "Copyright (C) Randy Nevin, 1989. Version 1.00\n" );
  110.     printf( "See source code for rights granted.\n\n" );
  111.     orient = 0; /* portrait mode */
  112.     resol = 150; /* 150 dots per inch */
  113.     zoom = 1; /* 6x6 cells */
  114.     oset = rset = zset = 0; /* so far, just defaults */
  115.     self = argv[0];
  116.     /* get rid of initial part of path */
  117.     if ((p = strrchr( self, '\\' )) || (p = strrchr( self, ':' )))
  118.         self = ++p;
  119.     if (argc < 2 || argc > 5) { /* need infile and up to 4 switches */
  120.         fprintf( stderr, "usage: %s [/P] [/L] [/Rn] [/Zm] infile\n",
  121.             self );
  122.         fprintf( stderr, " P = portrait orientation\n" );
  123.         fprintf( stderr, " L = landscape orientation\n" );
  124.         fprintf( stderr, " n = resolution (75,100,150,300)\n" );
  125.         fprintf( stderr, " m = zoom (0,1,2,3)\n" );
  126.         exit( -1 );
  127.         }
  128.     for (i = 1; i < argc-1; i++) { /* process switches */
  129.         if (*argv[i] == '/' && (*(argv[i]+1) == 'P'
  130.             || *(argv[i]+1) == 'p') && *(argv[i]+2) == 0) {
  131.             if (oset)
  132.                 fprintf( stderr, "duplicate orientation %s\n",
  133.                     argv[i] );
  134.             else {
  135.                 oset = 1;
  136.                 orient = 0;
  137.                 }
  138.             }
  139.         else if (*argv[i] == '/' && (*(argv[i]+1) == 'L'
  140.             || *(argv[i]+1) == 'l') && *(argv[i]+2) == 0) {
  141.             if (oset)
  142.                 fprintf( stderr, "duplicate orientation %s\n",
  143.                     argv[i] );
  144.             else {
  145.                 oset = 1;
  146.                 orient = 1;
  147.                 }
  148.             }
  149.         else if (*argv[i] == '/' && (*(argv[i]+1) == 'R'
  150.             || *(argv[i]+1) == 'r')) {
  151.             if (rset)
  152.                 fprintf( stderr, "duplicate resolution %s\n",
  153.                     argv[i] );
  154.             else {
  155.                 rset = 1;
  156.                 resol = atoi( argv[i]+2 );
  157.                 }
  158.             }
  159.         else if (*argv[i] == '/' && (*(argv[i]+1) == 'Z'
  160.             || *(argv[i]+1) == 'z')) {
  161.             if (zset)
  162.                 fprintf( stderr, "duplicate zoom %s\n",
  163.                     argv[i] );
  164.             else {
  165.                 zset = 1;
  166.                 zoom = atoi( argv[i]+2 );
  167.                 }
  168.             }
  169.         else
  170.             fprintf( stderr, "unknown option %s\n", argv[i] );
  171.         }
  172.     if (!(fp = fopen( argv[argc-1], "rb" ))) {
  173.         fprintf( stderr, "can't open %s\n", argv[argc-1] );
  174.         exit( -1 );
  175.         }
  176.     /* fetch the board dimensions */
  177.     if ((i = getc( fp )) == EOF || (j = getc( fp )) == EOF) {
  178.         fprintf( stderr, "premature eof\n" );
  179.         exit( -1 );
  180.         }
  181.     Nrows = (i & 0xFF) | ((j << 8) & 0xFF00);
  182.     if ((i = getc( fp )) == EOF || (j = getc( fp )) == EOF) {
  183.         fprintf( stderr, "premature eof\n" );
  184.         exit( -1 );
  185.         }
  186.     Ncols = (i & 0xFF) | ((j << 8) & 0xFF00);
  187.     InitBoard(); /* allocate memory for data structures */
  188.     for (r = 0; r < Nrows; r++) { /* read in the board, row by column */
  189.         for (c = 0; c < Ncols; c++) {
  190.             /* first do top-side */
  191.             if ((i1 = getc( fp )) == EOF
  192.                 || (i2 = getc( fp )) == EOF
  193.                 || (i3 = getc( fp )) == EOF
  194.                 || (i4 = getc( fp )) == EOF) {
  195.                 fprintf( stderr, "premature eof\n" );
  196.                 exit( -1 );
  197.                 }
  198.             x = (long)i1 | (((long)i2) << 8)
  199.                 | (((long)i3) << 16) | (((long)i4) << 24);
  200.             SetCell( r, c, TOP, x );
  201.             /* then do bottom-side */
  202.             if ((i1 = getc( fp )) == EOF
  203.                 || (i2 = getc( fp )) == EOF
  204.                 || (i3 = getc( fp )) == EOF
  205.                 || (i4 = getc( fp )) == EOF) {
  206.                 fprintf( stderr, "premature eof\n" );
  207.                 exit( -1 );
  208.                 }
  209.             x = (long)i1 | (((long)i2) << 8)
  210.                 | (((long)i3) << 16) | (((long)i4) << 24);
  211.             SetCell( r, c, BOTTOM, x );
  212.             }
  213.         }
  214.     nbytes = (Ncols * size[zoom] + 7) / 8;
  215.     dofile( "H",   H   );
  216.     dofile( "T",   T   );
  217.     dofile( "B",   B   );
  218.     dofile( "HT",  HT  );
  219.     dofile( "HB",  HB  );
  220.     dofile( "HTB", HTB );
  221.     exit( 0 );
  222.     }
  223.  
  224. static void dofile ( p, i ) /* create a board image file */
  225.     char *p;
  226.     int i;
  227.     {
  228.     FILE *fp;
  229.  
  230.     printf( "producing %s image file\n", p );
  231.     currnt = i;
  232.     if (!(fp = fopen( p, "wb" ))) {
  233.         fprintf( stderr, "can't open %s\n", p );
  234.         exit( -1 );
  235.         }
  236.     prolog( fp ); /* initial laser printer commands */    
  237.     doimage( fp ); /* create the board image */
  238.     epilog( fp ); /* final laser printer commands */
  239.     if (fclose( fp )) {
  240.         fprintf( stderr, "can't close %s\n", p );
  241.         exit( -1 );
  242.         }
  243.     }
  244.  
  245. static void prolog ( fp ) /* output initial laser printer commands */
  246.     register FILE *fp;
  247.     {
  248.     putc( 0x1B, fp );        /* <esc> */
  249.     putc( 'E', fp );        /* reset */
  250.     putc( 0x1B, fp );        /* <esc> */
  251.     fprintf( fp, "&l%dO", orient );    /* set image orientation */
  252.     putc( 0x1B, fp );        /* <esc> */
  253.     fprintf( fp, "&a10R" );        /* cursor to row 10 */
  254.     putc( 0x1B, fp );        /* <esc> */
  255.     fprintf( fp, "&a10C" );        /* cursor to column 10 */
  256.     putc( 0x1B, fp );        /* <esc> */
  257.     fprintf( fp, "*t%dR", resol );    /* set resolution in dots per inch */
  258.     putc( 0x1B, fp );        /* <esc> */
  259.     fprintf( fp, "*r1A" );        /* start graphics at cursor */
  260.     }
  261.  
  262. static void epilog ( fp ) /* output final laser printer commands */
  263.     register FILE *fp;
  264.     {
  265.     putc( 0x1B, fp );    /* <esc> */
  266.     fprintf( fp, "*rB" );    /* end graphics */
  267.     putc( 0x12, fp );    /* formfeed to eject paper */
  268.     putc( 0x1B, fp );    /* <esc> */
  269.     putc( 'E', fp );    /* reset */
  270.     }
  271.  
  272. static void doimage ( fp ) /* create the board image, row by column */
  273.     FILE *fp;
  274.     {
  275.     register int r, c;
  276.     int ir;
  277.     long x, y;
  278.  
  279.     for (r = Nrows-1; r >= 0; r--) { /* each row */
  280.         for (ir = size[zoom]-1; ir >= 0; ir--) { /* each scan line */
  281.             putc( 0x1B, fp );    /* <esc> */
  282.             fprintf( fp, "*b%dW", nbytes );
  283.             initbit();
  284.             for (c = 0; c < Ncols; c++) {
  285.                 x = GetCell( r, c, TOP );
  286.                 y = GetCell( r, c, BOTTOM );
  287.                 map( x, y, ir, fp );
  288.                 }
  289.             flushbit( fp );
  290.             }
  291.         }
  292.     }
  293.  
  294. struct x { /* group the bit templates for an object */
  295.     long t;            /* the object type    */
  296.     char t0[ZOOM0][ZOOM0];    /* tiny zoom template    */
  297.     char t1[ZOOM1][ZOOM1];    /* small zoom template    */
  298.     char t2[ZOOM2][ZOOM2];    /* medium zoom template    */
  299.     char t3[ZOOM3][ZOOM3];    /* large zoom template    */
  300.     };
  301.  
  302. extern struct x y1[];  /* hole templates        */
  303. extern struct x y2[];  /* hole-related templates    */
  304. extern struct x y3[];  /* non-hole-related templates    */
  305.  
  306. extern int z1;  /* number of hole types            */
  307. extern int z2;  /* number of hole-related types        */
  308. extern int z3;  /* number of non-hole-related types    */
  309.  
  310. #define domap1(v)    { int i; \
  311.               for (i = 0; i < z1; i++) { \
  312.                 if (v & (y1[i].t)) { \
  313.                     if (zoom == 0) \
  314.                         bit |= y1[i].t0[ir][ic]; \
  315.                     else if (zoom == 1) \
  316.                         bit |= y1[i].t1[ir][ic]; \
  317.                     else if (zoom == 2) \
  318.                         bit |= y1[i].t2[ir][ic]; \
  319.                     else if (zoom == 3) \
  320.                         bit |= y1[i].t3[ir][ic]; \
  321.                     } \
  322.                 if (bit) \
  323.                     break; \
  324.                 } }
  325.  
  326. #define domap2(v)    { int i; \
  327.               for (i = 0; i < z2; i++) { \
  328.                 if (v & (y2[i].t)) { \
  329.                     if (zoom == 0) \
  330.                         bit |= y2[i].t0[ir][ic]; \
  331.                     else if (zoom == 1) \
  332.                         bit |= y2[i].t1[ir][ic]; \
  333.                     else if (zoom == 2) \
  334.                         bit |= y2[i].t2[ir][ic]; \
  335.                     else if (zoom == 3) \
  336.                         bit |= y2[i].t3[ir][ic]; \
  337.                     } \
  338.                 if (bit) \
  339.                     break; \
  340.                 } }
  341.  
  342. #define domap3(v)    { int i; \
  343.               for (i = 0; i < z3; i++) { \
  344.                 if (v & (y3[i].t)) { \
  345.                     if (zoom == 0) \
  346.                         bit |= y3[i].t0[ir][ic]; \
  347.                     else if (zoom == 1) \
  348.                         bit |= y3[i].t1[ir][ic]; \
  349.                     else if (zoom == 2) \
  350.                         bit |= y3[i].t2[ir][ic]; \
  351.                     else if (zoom == 3) \
  352.                         bit |= y3[i].t3[ir][ic]; \
  353.                     } \
  354.                 if (bit) \
  355.                     break; \
  356.                 } }
  357.  
  358. static void map ( v0, v1, ir, fp ) /* map a cell to the image */
  359.     long v0, v1;
  360.     int ir;
  361.     FILE *fp;
  362.     {
  363.     register int ic, bit;
  364.  
  365.     for (ic = 0; ic < size[zoom]; ic++) { /* do each scan column */
  366.         bit = 0;
  367.         if (v0 & HOLE) {
  368.             if (currnt & H) /* plot holes? */
  369.                 domap1( v0 );
  370.             if (!bit && (currnt & T)) /* plot top-side? */
  371.                 domap2( v0 );
  372.             if (!bit && (currnt & B)) /* plot bottom-side? */
  373.                 domap2( v1 );
  374.             }
  375.         else {
  376.             if (v0 && (currnt & T)) /* plot top-side? */
  377.                 domap3( v0 );
  378.             if (!bit && v1 && (currnt & B)) /* plot bottom-side? */
  379.                 domap3( v1 );
  380.             }
  381.         outbit( bit, fp );
  382.         }
  383.     }
  384.  
  385. static int shift; /* how far to shift next bit */
  386. static char byte; /* the byte buffer */
  387.  
  388. static void initbit () { /* initialize bit output */
  389.     byte = 0;
  390.     shift = 7;
  391.     }
  392.  
  393. static void flushbit ( fp ) /* flush bit output */
  394.     FILE *fp;
  395.     {
  396.     if (shift != 7) /* buffer empty? */
  397.         putc( byte, fp ); /* no, output partial byte */
  398.     }
  399.  
  400. static void outbit( bit, fp ) /* output a bit using byte buffering */
  401.     int bit;
  402.     FILE *fp;
  403.     {
  404.     byte |= ((char)bit << shift);
  405.     if (!shift) {
  406.         putc( byte, fp );
  407.         byte = 0;
  408.         shift = 7;
  409.         }
  410.     else
  411.         shift--;
  412.     }
  413.